package com.start.common.dic;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.start.common.configs.StartTokenConfig;
import com.start.common.dataImport.ExcelActionType;
import com.start.common.tools.SpringContextTools;
import com.start.common.utils.TreeModelUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

@Slf4j
public class StartDynamicFormMapperHandler extends BaseExcelMapperHandler<Map> {
    private final String columnType;
    private StartTokenConfig tokenConfig;
    private String userToken;
    private JSONObject column;
    private static final String dicDataTreeComponents = "cascader,tree";
    private static final String dicDataComponents = "select,radio,checkbox,switch," + dicDataTreeComponents;
    private static final String dateTimeFormatComponents = "date,datetime,time";
    private static Pattern pattern = Pattern.compile("^http://||^https://", Pattern.DOTALL);
    private String labelDateFormat = "yyyy-MM-dd HH:mm:ss";
    private String valueDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    private final String prop;
    private final String title;

    public StartDynamicFormMapperHandler(JSONObject column, ExcelActionType excelActionType, StartTokenConfig tokenConfig, String userToken) {
        super(excelActionType);
        this.column = column;
        columnType = column.containsKey("type") ? column.getString("type") : "input";
        this.tokenConfig = tokenConfig;
        this.userToken = userToken;
        prop = column.getString("prop");
        title = !column.containsKey("label") ? prop : StringUtils.isNotBlank(column.getString("label")) ? column.getString("label") : prop;
        if (excelActionType != ExcelActionType.EXCEl_TEMPLATE) {
            this.loadMapperData();
        }
        if (!dateTimeFormatComponents.contains(columnType)) {
            return;
        }
        if (column.containsKey("format")) {
            labelDateFormat = column.getString("format");
            labelDateFormat = labelDateFormat.replace("Y", "y");
        }
        if (column.containsKey("valueFormat")) {
            valueDateTimeFormat = column.getString("valueFormat");
            valueDateTimeFormat = valueDateTimeFormat.replace("Y", "y");
        }
    }

    public String getTitle() {
        return title;
    }

    public String getFieldName() {
        return prop;
    }

    @Override
    public void loadMapperData() {
        if (!dicDataComponents.contains(columnType)) {
            return;
        }
        JSONArray dicData = null;
        if (column.containsKey("dicData") && !column.getJSONArray("dicData").isEmpty()) {
            dicData = loadLocalDicData();
        }
        if (column.containsKey("dicUrl") && StringUtils.isNotEmpty(column.getString("dicUrl"))) {
            dicData = loadRemoteDicData();
        }
        analysisDicData(dicData);
    }

    private JSONArray loadLocalDicData() {
        if (!column.containsKey("dicData")) {
            return null;
        }
        return column.getJSONArray("dicData");
    }

    /**
     * 处理远程字典类型数据
     */
    private JSONArray loadRemoteDicData() {
        String url = column.getString("dicUrl");
        url = url.replace("#{baseUrl}", "/");
        if (!pattern.matcher(url).matches()) {
            String contextPath = SpringContextTools.getContextPath();
            if (contextPath.startsWith("/")) {
                contextPath = contextPath.substring(1);
            }
            if (url.startsWith("/")) {
                url = url.substring(1);
            }
            if (url.startsWith(contextPath + "/")) {
                url = url.substring(contextPath.length());
            }
            Integer serverPort = SpringContextTools.getServerPort();
            url = "127.0.0.1:" + serverPort + "/" + contextPath + "/" + url;
            url = ReUtil.replaceAll(url, "/+", "/");
            url = "http://" + url;
        }
        String dicMethod = column.containsKey("dicMethod") ? column.getString("dicMethod") : "get";
        JSONObject dicQuery = column.containsKey("dicQuery") ? column.getJSONObject("dicQuery") : new JSONObject();
        HttpRequest httpRequest = null;
        if (dicMethod.equalsIgnoreCase("get")) {
            StringBuilder tempUrlParameter = new StringBuilder();
            if (!dicQuery.isEmpty()) {
                Set<Map.Entry<String, Object>> entries = dicQuery.entrySet();
                for (Map.Entry<String, Object> entrie : entries) {
                    tempUrlParameter.append(entrie.getKey());
                    tempUrlParameter.append("=");
                    tempUrlParameter.append(Convert.toStr(entrie.getValue()));
                }
            }
            if (url.contains("?")) {
                int index = url.indexOf("?");
                String tempUrl = url.substring(0, index);
                tempUrl += "?" + tempUrlParameter.toString();
                tempUrl += "&" + url.substring(index + 1);
                url = tempUrl;
            } else {
                url += "?" + tempUrlParameter;
            }
            httpRequest = HttpRequest.get(url);
        } else {
            httpRequest = HttpRequest.post(url).body(dicQuery.toJSONString());
        }
        if (tokenConfig != null) {
            httpRequest = httpRequest.header(tokenConfig.getTokenKey(), tokenConfig.getTokenValuePrefix() + userToken);
        }
        HttpResponse execute = httpRequest.execute();
        if (execute.getStatus() != 200) {
            log.error("请求错误：" + httpRequest.getUrl());
            return null;
        }
        JSONObject result = JSONObject.parseObject(execute.body());
        if (!result.containsKey("data")) {
            log.warn("远程数据中未找到有效数据：" + execute.body());
            return null;
        }
        return result.getJSONArray("data");

    }

    private void analysisDicData(JSONArray array) {
        if (array == null || array.isEmpty()) return;
        String labelKey = "label";
        String valueKey = "value";
        if (column.containsKey("props")) {
            JSONObject props = column.getJSONObject("props");
            if (props.containsKey("label")) {
                labelKey = props.getString("label");
            }
            if (props.containsKey("value")) {
                valueKey = props.getString("value");
            }
        }
        String mapperLabelKey = excelActionType == ExcelActionType.EXCEL_IMPORT ? labelKey : valueKey;
        String mapperValueKey = excelActionType == ExcelActionType.EXCEL_IMPORT ? valueKey : labelKey;
        if (dicDataTreeComponents.contains(columnType)) {
            String childrenKey = "children";
            if (column.containsKey("treeProps") && !column.getJSONObject("treeProps").isEmpty()) {
                JSONObject treeProps = column.getJSONObject("treeProps");
                if (treeProps.containsKey("children")) {
                    childrenKey = treeProps.getString("children");
                }
            }

            TreeModelUtils.treeToList(array, valueKey, null, childrenKey, null, item -> {
                this.getMapperTableData().put(item.getString(mapperLabelKey), item.getString(mapperValueKey));
            });
        }
        for (int i = 0; i < array.size(); i++) {
            JSONObject itemData = array.getJSONObject(i);
            this.getMapperTableData().put(itemData.getString(mapperLabelKey), itemData.getString(mapperValueKey));
        }
    }

    /**
     * 获取导入参数
     *
     * @param value
     * @return
     */
    @Override
    public Object getImportValue(String value) {
        if (StringUtils.isEmpty(value))
            return null;
        if (!dicDataComponents.contains(columnType)) {
            return value;
        }
        return handlerMapper(value);
    }


    /**
     * 获取导出参数
     *
     * @param obj
     * @return
     */
    @Override
    public String analysisExportValue(Map obj) {
        if (!obj.containsKey(prop))
            return null;
        Object valObj = obj.get(prop);
        if (valObj == null) {
            return null;
        }
        String value = Convert.toStr(valObj);
        if (dateTimeFormatComponents.contains(columnType)) {
            return handlerExportDateTime(value);
        }
        if (dicDataComponents.contains(columnType)) {
            return handlerMapper(value);
        }
        return value;
    }

    /**
     * 处理时间类型数据
     *
     * @param value
     * @return
     */
    private String handlerExportDateTime(String value) {
        if (StringUtils.isAllBlank(value)) {
            return value;
        }
        try {
            LocalDateTime parse;
            if (value.contains("T")) {
                parse = LocalDateTimeUtil.parse(value);
            } else {
                parse = LocalDateTimeUtil.parse(value, valueDateTimeFormat);
            }
            return LocalDateTimeUtil.format(parse, labelDateFormat);
        } catch (Exception e) {
            return value;
        }
    }


}
